package com.cory.module.job.core.handle;

import java.util.List;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import com.cory.boot.domain.CustomRuntimeException;
import com.cory.module.job.domain.entity.JobAsync;
import com.cory.module.job.domain.entity.JobAsyncDetail;
import com.cory.module.job.service.JobAsyncDetailService;
import com.cory.module.job.service.JobAsyncService;

/**
 * @author xiongcong
 * @date 2023-05-09
 */
public abstract class AsyncJobHandle {
    @Autowired
    private JobAsyncService JobAsyncService;
    
    @Autowired
    private JobAsyncDetailService jobAsyncDetailService;
    
    @Resource
    private DataSourceTransactionManager transactionManager;
    @Resource
    private TransactionDefinition transactionDefinition;

    public void run(JobAsync job) {
        List<JobAsyncDetail> details = jobAsyncDetailService.runList(job.getId());
        
        int okNum = 0, errorNum = 0;
        while (details.size() > 0) {
            for (JobAsyncDetail detail : details) {
                boolean ret = this.run(job, detail);
                if (ret) {
                    okNum++;
                } else {
                    errorNum++;
                }
            }
            
            JobAsync update = new JobAsync();
            update.setId(job.getId());
            update.setOkNum(job.getOkNum() + okNum);
            update.setErrorNum(job.getErrorNum() + errorNum);
            JobAsyncService.updateById(update);
            
            details = jobAsyncDetailService.runList(job.getId());
        }
        
        JobAsync update = new JobAsync();
        update.setId(job.getId());
        update.setState(1);
        JobAsyncService.updateById(update);
    }
    
    protected boolean run(JobAsync job, JobAsyncDetail detail) {
        jobAsyncDetailService.updateState(detail.getId(), 0);
        boolean ret = false;
        String errorMsg = null;
        
        TransactionStatus ts = transactionManager.getTransaction(transactionDefinition);
        try {
            ret = this.handle(job, detail);
            transactionManager.commit(ts);
        } catch(CustomRuntimeException e) {
            errorMsg = e.getMessage();
            transactionManager.rollback(ts);
        } catch(Exception e) {
            errorMsg = "执行错误";
            transactionManager.rollback(ts);
        }
        
        JobAsyncDetail update = new JobAsyncDetail();
        update.setId(detail.getId());
        if (ret) {
            update.setState(1);
        } else {
            update.setState(2);
            update.setErrorMsg(errorMsg);
        }
        jobAsyncDetailService.updateById(update);
        
        return ret;
    }
    
    protected abstract boolean handle(JobAsync job, JobAsyncDetail detail);
}
